package com.sinszm.wechat.service.impl;

import com.fcibook.quick.http.QuickHttp;
import com.sinszm.common.exception.ApiException;
import com.sinszm.wechat.configuration.WxProperties;
import com.sinszm.wechat.dao.DbWeChatAppRelRepository;
import com.sinszm.wechat.dao.DbWeChatCommonRepository;
import com.sinszm.wechat.dao.entity.DbWeChatAppRel;
import com.sinszm.wechat.dao.entity.DbWeChatCommon;
import com.sinszm.wechat.service.WeChatService;
import com.sinszm.wechat.util.Constant;
import org.apache.commons.codec.Charsets;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 重定向业务处理
 *
 * @author chenjianbo
 * @date 2020-3-8
 */
@Service
public class WeChatServiceImpl implements WeChatService {

    @Resource
    private DbWeChatAppRelRepository dbWeChatAppRelRepository;

    @Resource
    private DbWeChatCommonRepository dbWeChatCommonRepository;

    @Resource
    private WxProperties wxProperties;

    private static final Logger logger = LoggerFactory.getLogger(WeChatService.class);

    @Override
    public String code(String userId, String userSecret) {
        if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(userSecret)) {
            throw new ApiException("CODE-ERR-01", "用户授权参数不能为空");
        }
        DbWeChatAppRel rel = dbWeChatAppRelRepository.getByUserIdAndUserSecret(userId, userSecret);
        if (rel == null) {
            throw new ApiException("CODE-ERR-02", "用户授权信息未找到");
        }
        DbWeChatCommon common = dbWeChatCommonRepository.getByAppId(rel.getAppId());
        if (common == null) {
            throw new ApiException("CODE-ERR-03", "公众号配置信息未找到");
        }
        String appId = common.getAppId();
        try {
            String redirectUri = URLEncoder.encode(
                    (wxProperties.isSsl() ? "https://":"http://") +
                            common.getAuthDomain() +
                            Constant.SECRET_URI,
                    Charsets.UTF_8.name()
            );
            String uri = wxProperties.getApi() + "?appid=" + appId +
                    "&redirect_uri=" + redirectUri +
                    "&response_type=code" +
                    "&scope=" + rel.getModule().getValue() +
                    "&state=" + rel.getId() +
                    "#wechat_redirect";
            return "redirect:" + uri;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace(System.err);
            throw new ApiException("CODE-ERR-04", "授权参数异常.");
        }
    }

    @Override
    public String result(String code, String state) {
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) {
            throw new ApiException("CODE-ERR-05", "用户授权参数不能为空");
        }
        DbWeChatAppRel rel = dbWeChatAppRelRepository.getOne(state);
        DbWeChatCommon common = dbWeChatCommonRepository.getByAppId(rel.getAppId());
        if (common == null) {
            throw new ApiException("CODE-ERR-03", "公众号配置信息未找到");
        }
        if (logger.isDebugEnabled()) {
            logger.info("code = {}, state = {}", code, state);
        }
        //请求换取openid等信息
        Map<String, String> param = new HashMap<>(4);
        param.put("appid", common.getAppId());
        param.put("secret", common.getAppSecret());
        param.put("code", code);
        param.put("grant_type", "authorization_code");
        String result = new QuickHttp().url(wxProperties.getToken()).get().addParames(param).text();
        Map<String, String> map = Json.fromJsonAsMap(String.class, result);
        if (logger.isDebugEnabled()) {
            logger.info(Json.toJson(map, JsonFormat.nice()));
        }
        String accessToken = map.getOrDefault("access_token", "");
        String openid = map.getOrDefault("openid", "");
        String errcode = map.getOrDefault("errcode", "0");
        return "redirect:" + rel.getRedirectAddress() +
                "?openid=" + openid +
                "&accessToken=" + accessToken +
                "&errcode=" + errcode;
    }

}
